package com.zxy.ziems.server.energy.service.impl;

import com.zxy.ziems.server.classify.service.ClassifyDevicePropertyService;
import com.zxy.ziems.server.classify.service.ClassifyService;
import com.zxy.ziems.server.constant.enums.DictCodeEnum;
import com.zxy.ziems.server.domain.DictItem;
import com.zxy.ziems.server.dto.DataQueryDto;
import com.zxy.ziems.server.energy.enums.EnergyDataTypeEnum;
import com.zxy.ziems.server.energy.service.DataChartDictService;
import com.zxy.ziems.server.energy.service.DataChartService;
import com.zxy.ziems.server.service.DictItemService;
import com.zxy.ziems.server.utils.AssertUtil;
import com.zxy.ziems.server.vo.*;
import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Copyright (C),
 * @ClassName: DataChartDictServiceImpl
 * @Author: yanzhiwei
 * @Description: 根据字典code获取数据
 * @Date: 2024/6/7 16:11
 */
@Service
public class DataChartDictServiceImpl implements DataChartDictService {

    @Autowired
    private DictItemService dictItemService;
    @Autowired
    private DataChartService dataChartService;
    @Autowired
    private ClassifyService classifyService;
    @Autowired
    private ClassifyDevicePropertyService classifyDevicePropertyService;


    @Nullable
    private String getclassifyId(String dictCode, String itemName) {
        String classifyId = null;
        // 获取字典配置分类项
        List<DictItem> dictItems = dictItemService.getByDictCode(dictCode);
        if (dictItems.isEmpty()) {
            classifyId = null;
        } else {
            DictItem dictItem = dictItems.stream().filter(m -> m.getItemName().equals(itemName)).findFirst().orElse(new DictItem());
            classifyId = dictItem.getItemCode();
        }
        AssertUtil.nonNull(classifyId, "未找到字典配置");
        return classifyId;
    }

    @Nullable
    private List<String> getclassifyIds(String dictCode, List<String> itemNames) {
        List<String> classifyIds = new ArrayList<>();
        // 获取字典配置分类项
        List<DictItem> dictItems = dictItemService.getByDictCode(dictCode);
        if (dictItems.isEmpty()) {
            return classifyIds;
        } else {
            DictItem dictItem = dictItems.stream().filter(m -> itemNames.contains(m.getItemName())).findFirst().orElse(new DictItem());
            classifyIds.add(dictItem.getItemCode());
        }
        AssertUtil.nonNull(classifyIds, "未找到字典配置");
        return classifyIds;
    }

    @Override
    public ChartVo thisData(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        dataQueryDto.setClassifyId(classifyId);
        return dataChartService.thisCycleData(dataQueryDto);
    }


    /**
     * 计算单价（费用/用量）
     *
     * @param dataQueryDto
     * @return
     */
    @Override
    public ChartVo thisDataCost(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        dataQueryDto.setClassifyId(classifyId);
        ChartCodeVo chartCodeVo = dataChartService.thisCycleDataAndCode(dataQueryDto);

        ChartVo chartVo = new ChartVo();
        chartVo.setXAxisList(chartCodeVo.getXAxisList());

        List<ChartYAxisVo> yAxisList = chartCodeVo.getYAxisList();
        List<ChartYAxisVo> codeyAxisList = chartCodeVo.getCodeyAxisList();


        List<ChartYAxisVo> yAxisVoList = oneInfo(yAxisList, codeyAxisList);

        chartVo.setYAxisList(yAxisVoList);
        return chartVo;
    }

    /**
     * 计算单价
     */
    private static List<ChartYAxisVo> oneInfo(List<ChartYAxisVo> yAxisList, List<ChartYAxisVo> codeyAxisList) {
        List<ChartYAxisVo> yAxisVoList = new ArrayList<>();
        // 计算成本
        for (int i = 0; i < yAxisList.size(); i++) {
            ChartYAxisVo chartYAxis1Vo = yAxisList.get(i);
            ChartYAxisVo chartYAxis2Vo = codeyAxisList.get(i);
            ChartYAxisVo chartYAxisVo = new ChartYAxisVo();
            BeanUtils.copyProperties(chartYAxis1Vo, chartYAxisVo);

            final List<BigDecimal> data1 = chartYAxis1Vo.getData();
            final List<BigDecimal> data2 = chartYAxis2Vo.getData();
            List<BigDecimal> datas = new ArrayList<>();
            for (int j = 0; j < data1.size(); j++) {
                BigDecimal bigDecimal1 = data1.get(j);
                BigDecimal bigDecimal2 = data2.get(j);
                BigDecimal bigDecimal = bigDecimal1.compareTo(BigDecimal.ZERO) == 0 ? BigDecimal.ZERO : bigDecimal2.divide(bigDecimal1, 2, RoundingMode.HALF_UP);
                datas.add(bigDecimal);
            }
            chartYAxisVo.setData(datas);
            yAxisVoList.add(chartYAxisVo);
        }

        return yAxisVoList;
    }

    @Override
    public ChartVo childData(DataQueryDto dataQueryDto) {
        // 根据字典ID和字典Name获取分类ID
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        // 根据分类ID获取下属的分类
        List<String> classifyIds = classifyService.getChildrenId(classifyId);
        dataQueryDto.setClassifyIdList(classifyIds);
        return dataChartService.compareBarChart(dataQueryDto);
    }

    @Override
    public void exportChildData(HttpServletResponse response, DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        List<String> classifyIds = classifyService.getChildrenId(classifyId);
        dataQueryDto.setClassifyIdList(classifyIds);
        dataChartService.exportChildData(response, dataQueryDto);


    }

    /**
     * 分类占比
     *
     * @param dataQueryDto
     * @return
     */
    @Override
    public List<PieChartVo> totalTypePie(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        dataQueryDto.setClassifyId(classifyId);
        return dataChartService.thisCycleDataPie(dataQueryDto);
    }


    @Override
    public ChartVo compareBarChart(DataQueryDto dataQueryDto) {
        List<String> classifyIds = getclassifyIds(dataQueryDto.getDictCode(), dataQueryDto.getItemNames());
        dataQueryDto.setClassifyIdList(classifyIds);
        return dataChartService.compareBarChart(dataQueryDto);
    }

    @Override
    public ChartVo compareBarChartEle(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        dataQueryDto.setClassifyId(classifyId);
        return dataChartService.compareBarChartEle(dataQueryDto);
    }

    @Override
    public ReportVo compareChartReport(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        List<String> classifyIds = classifyService.getChildrenId(classifyId);
        dataQueryDto.setClassifyIdList(classifyIds);
        return dataChartService.compareChartReport(dataQueryDto);
    }

    @Override
    public ChartCodeVo compareCodeAndInfo(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        List<String> classifyIds = classifyService.getChildrenId(classifyId);
        dataQueryDto.setClassifyIdList(classifyIds);
        // 用量
        ChartVo chartVo1 = dataChartService.compareBarChart(dataQueryDto);

        // 费用
        dataQueryDto.setDataType(EnergyDataTypeEnum.CODE.getCode());
        ChartVo chartVo2 = dataChartService.compareBarChart(dataQueryDto);

        List<ChartYAxisVo> yAxisList = chartVo1.getYAxisList().stream().map(m -> {
            m.setName(m.getName() + "用量");
            return m;
        }).collect(Collectors.toList());

        List<ChartYAxisVo> codeyAxisList = chartVo2.getYAxisList().stream().map(m -> {
            m.setName(m.getName() + "费用");
            return m;
        }).collect(Collectors.toList());


        ChartCodeVo chartVo = ChartCodeVo.builder()
                .xAxisList(chartVo1.getXAxisList())
                .yAxisList(yAxisList)
                .codeyAxisList(codeyAxisList)
                .build();

        return chartVo;
    }

    @Override
    public ChartVo compareOneCodeAndInfo(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        List<String> classifyIds = classifyService.getChildrenId(classifyId);
        dataQueryDto.setClassifyIdList(classifyIds);
        ChartCodeVo chartCodeVo = dataChartService.compareDataAndCode(dataQueryDto);

        ChartVo chartVo = new ChartVo();
        chartVo.setXAxisList(chartCodeVo.getXAxisList());

        List<ChartYAxisVo> yAxisList = chartCodeVo.getYAxisList();
        List<ChartYAxisVo> codeyAxisList = chartCodeVo.getCodeyAxisList();


        List<ChartYAxisVo> yAxisVoList = oneInfo(yAxisList, codeyAxisList);

        chartVo.setYAxisList(yAxisVoList);
        return chartVo;
    }

    @Override
    public ChartCodeVo totalCodeAndInfo(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        dataQueryDto.setClassifyId(classifyId);

        // 用量
        ChartVo chartVo1 = dataChartService.thisCycleData(dataQueryDto);

        // 费用
        dataQueryDto.setDataType(EnergyDataTypeEnum.CODE.getCode());
        ChartVo chartVo2 = dataChartService.thisCycleData(dataQueryDto);

        List<ChartYAxisVo> yAxisList = chartVo1.getYAxisList().stream().map(m -> {
            m.setName(m.getName() + "用量");
            return m;
        }).collect(Collectors.toList());

        List<ChartYAxisVo> codeyAxisList = chartVo2.getYAxisList().stream().map(m -> {
            m.setName(m.getName() + "费用");
            return m;
        }).collect(Collectors.toList());


        ChartCodeVo chartVo = ChartCodeVo.builder()
                .xAxisList(chartVo1.getXAxisList())
                .yAxisList(yAxisList)
                .codeyAxisList(codeyAxisList)
                .build();

        return chartVo;
    }

    @Override
    public ChartCodeVo totalInfoAndOneInfo(DataQueryDto dataQueryDto) {
        String classifyId = getclassifyId(dataQueryDto.getDictCode(), dataQueryDto.getItemName());
        dataQueryDto.setClassifyId(classifyId);

        // 用量
        ChartVo chartVo1 = dataChartService.thisCycleData(dataQueryDto);

        // 费用
        dataQueryDto.setDataType(EnergyDataTypeEnum.CODE.getCode());
        ChartVo chartVo2 = dataChartService.thisCycleData(dataQueryDto);

        List<ChartYAxisVo> yAxisList = chartVo1.getYAxisList().stream().map(m -> {
            m.setName(m.getName() + "用量");
            return m;
        }).collect(Collectors.toList());

        List<ChartYAxisVo> codeyAxisList = chartVo2.getYAxisList().stream().map(m -> {
            m.setName(m.getName() + "单耗");
            return m;
        }).collect(Collectors.toList());

        List<ChartYAxisVo> yAxisVoList = oneInfo(yAxisList, codeyAxisList);


        ChartCodeVo chartVo = ChartCodeVo.builder()
                .xAxisList(chartVo1.getXAxisList())
                .yAxisList(yAxisList)
                .codeyAxisList(yAxisVoList)
                .build();
        return chartVo;
    }

    @Override
    public HashMap<String, Object> pageUi(DataQueryDto dataQueryDto) {
        List<PieChartVo> pieChartVos = totalTypePie(dataQueryDto);

        ChartCodeVo chartCodeVo = totalInfoAndOneInfo(dataQueryDto);

        ChartCodeVo chartCodeVo1 = totalInfoAndOneInfo(dataQueryDto);

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("ratid", pieChartVos);
        hashMap.put("base", chartCodeVo);
        hashMap.put("technology", chartCodeVo1);
        return hashMap;
    }

    /**
     * 水科计算原水，制成水量
     *
     * @param dataQueryDto
     * @return
     */
    @Override
    public List<WaterReportVo> compareWaterInfoReport(DataQueryDto dataQueryDto) {


        // 原水
        String classifyId1 = getclassifyId(DictCodeEnum.WATER_MADE.getCode(), "原水量");
        dataQueryDto.setClassifyId(classifyId1);
        ChartVo chartVo1 = dataChartService.thisCycleData(dataQueryDto);
        final List<String> xAxisList = chartVo1.getXAxisList();
        final List<ChartYAxisVo> yAxisList1 = chartVo1.getYAxisList();
        ChartYAxisVo chartYAxisVo1 = yAxisList1.get(0);
        List<BigDecimal> data1 = chartYAxisVo1.getData();

        // 制成水
        String classifyId2 = getclassifyId(DictCodeEnum.WATER_MADE.getCode(), "制成水量");
        dataQueryDto.setClassifyId(classifyId2);
        ChartVo chartVo2 = dataChartService.thisCycleData(dataQueryDto);
        List<ChartYAxisVo> yAxisList2 = chartVo2.getYAxisList();
        ChartYAxisVo chartYAxisVo2 = yAxisList2.get(0);
        List<BigDecimal> data2 = chartYAxisVo2.getData();

        List<WaterReportVo> waterReportVoList = new ArrayList<>();
        for (int i = 0; i < xAxisList.size(); i++) {
            String date = xAxisList.get(i);

            BigDecimal b1 = data1.get(i);

            BigDecimal b2 = data2.get(i);

            WaterReportVo waterReportVo = new WaterReportVo();
            waterReportVo.setDate(date);
            waterReportVo.setRawWater(b1);
            waterReportVo.setMakeWater(b2);
            waterReportVo.setMakeRate(BigDecimal.ZERO.compareTo(b1) == 0 || BigDecimal.ZERO.compareTo(b2) == 0 ? BigDecimal.ZERO : b2.divide(b1, 2, RoundingMode.HALF_UP));
            waterReportVoList.add(waterReportVo);
        }
        return waterReportVoList;
    }


    @Override
    public ChartVo dataChain(DataQueryDto dataQueryDto) {
        return dataChartService.dataChain(dataQueryDto);
    }

    /**
     * 制成率数据格式化
     *
     * @param dataQueryDto
     * @return
     */
    @Override
    public ChartVo thisDataWaterInfoReport(DataQueryDto dataQueryDto) {
        final List<WaterReportVo> waterReportVoList = compareWaterInfoReport(dataQueryDto);
        List<String> xAxisList = new ArrayList<>();
        List<BigDecimal> data = new ArrayList<>();
        List<ChartYAxisVo> yAxisList = new ArrayList<>();

        for (WaterReportVo waterReportVo : waterReportVoList) {
            xAxisList.add(waterReportVo.getDate());
            data.add(waterReportVo.getRawWater());
        }
        ChartYAxisVo chartYAxisVo = new ChartYAxisVo();
        chartYAxisVo.setData(data);
        yAxisList.add(chartYAxisVo);


        ChartVo chartVo = new ChartVo();
        chartVo.setXAxisList(xAxisList);
        chartVo.setYAxisList(yAxisList);

        return chartVo;
    }


}
